namespace Jsl.FxCop
{
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using Microsoft.FxCop.Sdk;

    /// <summary>
    /// Holds a collection of already processed <see cref="ComponentDictionary"/>s.
    /// </summary>
    /// <remarks>
    /// Since I wanted to test my custom rules at the field level, I needed some way of caching the processed
    /// InitializedComponents since I would be looking at them once per field.
    /// </remarks>
    public static class ComponentsCache
    {
        private static readonly List<ComponentDictionary> componentDictionaries = new List<ComponentDictionary>();

        /// <summary>
        /// Clears the cache.
        /// </summary>
        public static void Clear()
        {
            ComponentsCache.componentDictionaries.Clear();
        }

        /// <summary>
        /// Gets the component dictionary for the specified type.
        /// </summary>
        /// <param name="type">The type to get the <see cref="ComponentDictionary"/> for.</param>
        /// <returns>The <see cref="ComponentDictionary"/> for the type.</returns>
        /// <remarks>
        /// The <see cref="ComponentDictionary"/> is created if it doesn't already exist.
        /// </remarks>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static ComponentDictionary GetComponentDictionary(TypeNode type)
        {
            // See if this type has already been processed.
            foreach (var componentDictionary in ComponentsCache.componentDictionaries)
            {
                if (componentDictionary.Type == type)
                {
                    return componentDictionary;
                }
            }

            // Process this type and add it to our collection.
            var newComponentDictionary = new ComponentDictionary(type);
            ComponentsCache.componentDictionaries.Add(newComponentDictionary);

            return newComponentDictionary;
        }
    }
}